from enum import Enum
from datetime import datetime
from typing import List, Optional
from uuid import UUID, uuid4
from sqlmodel import Field, select, and_, desc

from sqlalchemy import Column, DateTime, String, Text, text, Integer
from bisheng.database.base import session_getter
from bisheng.database.models.base import SQLModelSerializable


class StatusEnum(Enum):
    STARTED = 0  # 开始状态
    FINISHED = 1  # 完成状态
    # SENDING = 2       # 发送中
    FAILED = 2  # 失败状态
    COMPLETED = 3  # 已完成状态

    def __str__(self):
        return self.name

    @classmethod
    def get_value(cls, name):
        return cls[name].value


class MetroFaultTaskBase(SQLModelSerializable):
    id: UUID = Field(nullable=False, primary_key=True, description='唯一ID')
    metro_fault_id: str = Field(nullable=False, description='地铁故障ID')
    equipment_id: str = Field(sa_column=Column(String(length=64), default=''), description='故障设备编号')
    suggestion_start_time: datetime = Field(nullable=False, description='建议开始时间')
    suggestion_end_time: datetime = Field(nullable=False, description='建议结束时间')
    suggestion: str = Field(sa_column=Column(Text), description='建议')
    maintenance_standard: str = Field(sa_column=Column(Text), description='检修标准，用于给出修程修治建议')
    strategy_name: str = Field(sa_column=Column(String(length=255),default=''),description='策略名称')
    strategy_number: str = Field(sa_column=Column(String(length=255), default=''), description='策略编号')
    level: str = Field(sa_column=Column(String(length=64), default=''), description='影响等级')
    error_msg: str = Field(sa_column=Column(Text), description='错误信息')
    create_time: Optional[datetime] = Field(
        sa_column=Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP')))
    update_time: Optional[datetime] = Field(
        sa_column=Column(DateTime,
                         nullable=False,
                         index=True,
                         server_default=text('CURRENT_TIMESTAMP'),
                         onupdate=text('CURRENT_TIMESTAMP')))
    status: int = Field(sa_column=Column(Integer, default=0), description='状态')


class MetroFaultTask(MetroFaultTaskBase, table=True):
    id: UUID = Field(default_factory=uuid4, primary_key=True, unique=True)


class MetroFaultTaskDao(MetroFaultTask):
    @classmethod
    def create_task(cls, task: MetroFaultTask) -> MetroFaultTask:
        """创建新的地铁故障任务"""
        with session_getter() as session:
            session.add(task)
            session.commit()
            session.refresh(task)
            return task

    @classmethod
    def update_task(cls, id: UUID, update_data: dict) -> Optional[MetroFaultTask]:
        """更新地铁故障任务"""
        with session_getter() as session:
            task = session.get(MetroFaultTask, id)
            if task:
                for key, value in update_data.items():
                    setattr(task, key, value)
                session.commit()
                session.refresh(task)
            return task

    @classmethod
    def update_self(cls, metro_fault_task: MetroFaultTask):
        with session_getter() as session:
            session.add(metro_fault_task)
            session.commit()
            session.refresh(metro_fault_task)
            return metro_fault_task

    @classmethod
    def search_tasks(cls,
                     metro_fault_id: Optional[str] = None,
                     equipment_id: Optional[str] = None,
                     suggestion_start_time: Optional[datetime] = None,
                     suggestion_end_time: Optional[datetime] = None,
                     status: Optional[int] = None) -> List[MetroFaultTask]:
        """
        根据多个条件搜索地铁故障任务

        :param metro_fault_id: 地铁故障ID
        :param equipment_id: 故障设备编号
        :param suggestion_start_time: 建议开始时间
        :param suggestion_end_time: 建议结束时间
        :param status: 状态
        :return: 符合条件的地铁故障任务列表
        """
        with session_getter() as session:
            query = select(MetroFaultTask)
            conditions = []

            if metro_fault_id:
                conditions.append(MetroFaultTask.metro_fault_id == metro_fault_id)
            if equipment_id:
                conditions.append(MetroFaultTask.equipment_id == equipment_id)
            if suggestion_start_time:
                conditions.append(MetroFaultTask.suggestion_start_time >= suggestion_start_time)
            if suggestion_end_time:
                conditions.append(MetroFaultTask.suggestion_end_time <= suggestion_end_time)
            if status is not None:
                conditions.append(MetroFaultTask.status == status)

            if conditions:
                query = query.where(and_(*conditions))

            return session.exec(query).all()

    @classmethod
    def get_first_by_equipment_id_and_non_zero_status(cls, equipment_id: str) -> Optional[MetroFaultTask]:
        """
        根据设备ID和非零状态获取第一个匹配的任务

        :param equipment_id: 设备ID
        :return: 匹配的 MetroFaultTaskBase 对象，如果没有找到则返回 None
        """
        with session_getter() as session:
            statement = select(MetroFaultTask).where(
                (MetroFaultTask.equipment_id == equipment_id) &
                (MetroFaultTask.status != StatusEnum.STARTED.value)
            ).order_by(desc(MetroFaultTask.create_time)).limit(1)

            result = session.exec(statement).first()

            return result

    @classmethod
    def get_by_equipment_id(cls,equipment_id: str):
        with session_getter() as session:
            statement = select(MetroFaultTask).where(
                MetroFaultTask.equipment_id == equipment_id
            ).order_by(desc(MetroFaultTask.create_time))

            result = session.exec(statement).all()

            return result
